package sv.com.seguros.dao.asg;

import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Vector;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import sv.com.seguros.dao.BaseDaoImpl;
import sv.com.seguros.dto.asg.AsgCliente;
import sv.com.seguros.dto.asg.AsgPoliza;
import sv.com.seguros.dto.ctg.CtgCatalogo;
import sv.com.seguros.exception.WebException;
import sv.com.seguros.web.controller.asg.AsgSeguroForm;
import sv.com.seguros.web.util.WebUtilidades;

public class AsgClienteDaoImpl extends BaseDaoImpl implements AsgClienteDao {

	@SuppressWarnings("unchecked")
	public boolean isClientExtis(AsgCliente asgCliente) throws WebException{
		if(asgCliente.getCtgTipoPersona() == null || asgCliente.getCtgTipoPersona().getCtgCatalogoId() <= 0) throw new WebException("TIPO PERSONA NO INDICADO");
		CtgCatalogo ctgTipoPersona = (CtgCatalogo) findById(CtgCatalogo.class, asgCliente.getCtgTipoPersona().getCtgCatalogoId());
		boolean ctgTipoPersonaNatural = WebUtilidades.CTG_TIPO_PERSONA_NATURAL.equals(ctgTipoPersona.getCtgCatalogoHijo());
		DetachedCriteria criteria = null;//DetachedCriteria.forClass(AsgCliente.class);
		if(asgCliente.getAsgClienteId() != null && asgCliente.getAsgClienteId() > 0){
			criteria = DetachedCriteria.forClass(AsgCliente.class);
			if(ctgTipoPersonaNatural) criteria.setProjection(Projections.projectionList().add(Projections.property("asgClienteDocumento1")));
			else criteria.setProjection(Projections.projectionList().add(Projections.property("asgClienteDocumento2")));
			criteria.add(Restrictions.eq("asgClienteId", asgCliente.getAsgClienteId()));
			List<String> asgClienteDocumentos = (List<String>) findByCriteria(criteria);
			if(!WebUtilidades.isEmptyList(asgClienteDocumentos)){
				if(ctgTipoPersonaNatural && StringUtils.trimToEmpty(asgClienteDocumentos.get(0)).equals(asgCliente.getAsgClienteDocumento1())) return true;
				else if(StringUtils.trimToEmpty(asgClienteDocumentos.get(0)).equals(asgCliente.getAsgClienteDocumento2())) return true;
			}
		}
		criteria = DetachedCriteria.forClass(AsgCliente.class);
		if(ctgTipoPersonaNatural) criteria.add(Restrictions.eq("asgClienteDocumento1", asgCliente.getAsgClienteDocumento1()));
		else criteria.add(Restrictions.eq("asgClienteDocumento2", asgCliente.getAsgClienteDocumento2()));
		List<AsgCliente> list = (List<AsgCliente>) findByCriteria(criteria);
		if(WebUtilidades.isEmptyList(list)) return false;
		else{
			AsgCliente asgClienteError = list.get(0);
			throw new WebException("Cliente con Documento <b>" + (ctgTipoPersonaNatural ? "DUI: " : "NIT: ") + 
					(ctgTipoPersonaNatural ? asgCliente.getAsgClienteDocumento1() : asgCliente.getAsgClienteDocumento2()) + 
					"</b> ya existe.<br /><b>Nombre Completo /Empresa: </b>" + asgClienteError.getAsgClienteNombreCompleto());
		}
	}
	
	public List<Object[]> doSearch(AsgSeguroForm asgSeguroForm) throws WebException{
		return doSearch(asgSeguroForm, false);
	}
	
	public List<Object[]> doSearchRenovacion(AsgSeguroForm asgSeguroForm) throws WebException{
		return doSearch(asgSeguroForm, true);
	}
	
	@SuppressWarnings("unchecked")
	private List<Object[]> doSearch(AsgSeguroForm asgSeguroForm, boolean renovacion) throws WebException{
		String hqlQuery = WebUtilidades.getQueryByName("asgCliente.doSearch");;
		if(renovacion){
			String renovacionVencidad = 
				", case " +
				"	when asgPoliza.asgPolizaFechaFinalizacion < '{SYSDATE}' then 1 " +
				"	when asgPoliza.asgPolizaFechaFinalizacion = '{SYSDATE}' then 2" +
				"	when asgPoliza.asgPolizaFechaFinalizacion > '{SYSDATE}' " +
				"		and asgPoliza.asgPolizaFechaFinalizacion <= '{SYSDATE_15}'  then 3" +
				"	else 4 " +
				" end ";
			renovacionVencidad = StringUtils.replace(renovacionVencidad, "{SYSDATE}", WebUtilidades.dateFormatAsYYYYMMDD.format(new Date()));
			Calendar calendar = Calendar.getInstance();
			calendar.add(Calendar.DAY_OF_MONTH, 15);
			renovacionVencidad = StringUtils.replace(renovacionVencidad, "{SYSDATE_15}", WebUtilidades.dateFormatAsYYYYMMDD.format(calendar.getTime()));
			hqlQuery = StringUtils.replace(hqlQuery, "{RENOVACION}", renovacionVencidad);
			hqlQuery = StringUtils.replace(hqlQuery, "{RENOVACION_ORDER}", ", asgPoliza.asgPolizaFechaFinalizacion");
		}else{
			hqlQuery = StringUtils.replace(hqlQuery, "{RENOVACION}", "");
			hqlQuery = StringUtils.replace(hqlQuery, "{RENOVACION_ORDER}", "");
		}
		Vector<Object> parameters = new Vector<Object>();
		String where = "";
		boolean addAnd = false;
		if(StringUtils.isNotBlank(asgSeguroForm.getAsgClienteNombreCompleto())){
			where += 
				" (" +
				"	upper(" +
					"concat(" +
						"coalesce(asgCliente.asgClientePrimerNombre, ''), ' '," +
						"coalesce(asgCliente.asgClienteSegundoNombre, ''), ' '," +
						"coalesce(asgCliente.asgClienteTercerNombre, ''), ' '," +
						"coalesce(asgCliente.asgClientePrimerApellido, ''), ' '," +
						"coalesce(asgCliente.asgClienteSegundoApellido, ''), ' '," +
						"coalesce(asgCliente.asgClienteApellidoCasada, ''))) like upper(?) or" +
				"	upper(coalesce(asgCliente.asgClienteNombreComercial, '')) like upper(?)" +
				")";
			parameters.add("%" + StringUtils.replace(asgSeguroForm.getAsgClienteNombreCompleto(), " ", "%") + "%");
			parameters.add("%" + StringUtils.replace(asgSeguroForm.getAsgClienteNombreCompleto(), " ", "%") + "%");
			addAnd = true;
		}
		if(renovacion){
			where += (addAnd ? " and " : "") + " asgPoliza.asgPolizaRenovada = '0' ";
			addAnd = true;
		}
		if(StringUtils.isNotBlank(asgSeguroForm.getAsgPolizaNumero())){
			where += (addAnd ? " and " : "") + " asgPoliza.asgPolizaNumero like upper(?) ";
			parameters.add("%" + asgSeguroForm.getAsgPolizaNumero() + "%");
			addAnd = true;
		}
		if(asgSeguroForm.getCtgAseguradoraId() != null && asgSeguroForm.getCtgAseguradoraId() > 0){
			where += (addAnd ? " and " : "") + " ctgAseguradora.ctgAseguradoraId = ? ";
			parameters.add(asgSeguroForm.getCtgAseguradoraId());
			addAnd = true;
		}
		if(asgSeguroForm.getCtgAsesorId() != null && asgSeguroForm.getCtgAsesorId() > 0){
			where += (addAnd ? " and " : "") + " ctgAsesor.ctgAsesorId = ? ";
			parameters.add(asgSeguroForm.getCtgAsesorId());
			addAnd = true;
		}
		if((StringUtils.isNotBlank(asgSeguroForm.getAsgFechaInicio1()) && 
				StringUtils.isNotBlank(asgSeguroForm.getAsgFechaInicio2()))){
			where += (addAnd ? " and " : "") + " asgPoliza.asgPolizaFechaInicio >= ? and  asgPoliza.asgPolizaFechaInicio <= ? ";
			parameters.add(asgSeguroForm.getAsgFechaInicio1());
			parameters.add(asgSeguroForm.getAsgFechaInicio2());
			addAnd = true;
		}
		if((StringUtils.isNotBlank(asgSeguroForm.getAsgFechaFinalizacion1()) && 
				StringUtils.isNotBlank(asgSeguroForm.getAsgFechaFinalizacion2()))){
			where += (addAnd ? " and " : "") + " asgPoliza.asgPolizaFechaFinalizacion >= ? and  asgPoliza.asgPolizaFechaFinalizacion <= ? ";
			parameters.add(asgSeguroForm.getAsgFechaFinalizacion1());
			parameters.add(asgSeguroForm.getAsgFechaFinalizacion2());
			addAnd = true;
		}
		hqlQuery = StringUtils.replace(hqlQuery, "{WHERE}", StringUtils.isNotBlank(where) ? (" where " + where) : "");
		try {
			return (List<Object[]>) findByHQLQuery(hqlQuery, parameters.toArray());
		} catch (Exception e) {
			throw new WebException("Problemas al ejecutar la busqueda de clientes y polizas");
		}
	}
	
	@SuppressWarnings("unchecked")
	public List<Object[]> findForPayDetail(AsgSeguroForm asgSeguroForm) throws WebException{
		String hqlQuery = WebUtilidades.getQueryByName("asgCliente.findForPaymentDetail");
		Vector<Object> parameters = new Vector<Object>();
		String where = "";
		boolean addAnd = false;
		
		if(StringUtils.isNotBlank(asgSeguroForm.getAsgClienteNombreCompleto())){
			where += 
				" (" +
				"	upper(" +
					"concat(" +
						"coalesce(asgCliente.asgClientePrimerNombre, ''), ' '," +
						"coalesce(asgCliente.asgClienteSegundoNombre, ''), ' '," +
						"coalesce(asgCliente.asgClienteTercerNombre, ''), ' '," +
						"coalesce(asgCliente.asgClientePrimerApellido, ''), ' '," +
						"coalesce(asgCliente.asgClienteSegundoApellido, ''), ' '," +
						"coalesce(asgCliente.asgClienteApellidoCasada, ''))) like upper(?) or" +
				"	upper(coalesce(asgCliente.asgClienteNombreComercial, '')) like upper(?)" +
				")";
			parameters.add("%" + StringUtils.replace(asgSeguroForm.getAsgClienteNombreCompleto(), " ", "%") + "%");
			parameters.add("%" + StringUtils.replace(asgSeguroForm.getAsgClienteNombreCompleto(), " ", "%") + "%");
			addAnd = true;
		}
		if(StringUtils.isNotBlank(asgSeguroForm.getAsgPolizaNumero())){
			where += (addAnd ? " and " : "") + " asgPoliza.asgPolizaNumero like upper(?) ";
			parameters.add("%" + asgSeguroForm.getAsgPolizaNumero() + "%");
			addAnd = true;
		}
		hqlQuery = StringUtils.replace(hqlQuery, "{WHERE}", StringUtils.isNotBlank(where) ? (" where " + where) : "");
		try {
			return (List<Object[]>) findByHQLQuery(hqlQuery, parameters.toArray());
		} catch (Exception e) {
			throw new WebException("Problemas al ejecutar la busqueda de clientes y polizas");
		}		
	}
	
	@SuppressWarnings("unchecked")
	public List<Object[]> findForSeguimientoDetail(AsgSeguroForm asgSeguroForm, String type) throws WebException{
		String hqlQuery = WebUtilidades.getQueryByName("asgCliente.findForSeguimientoDetail");
		Vector<Object> parameters = new Vector<Object>();
		String where = "";
		boolean addAnd = false;
		
		if(StringUtils.isNotBlank(asgSeguroForm.getAsgClienteNombreCompleto())){
			where += 
				" (" +
				"	upper(" +
					"concat(" +
						"coalesce(asgCliente.asgClientePrimerNombre, ''), ' '," +
						"coalesce(asgCliente.asgClienteSegundoNombre, ''), ' '," +
						"coalesce(asgCliente.asgClienteTercerNombre, ''), ' '," +
						"coalesce(asgCliente.asgClientePrimerApellido, ''), ' '," +
						"coalesce(asgCliente.asgClienteSegundoApellido, ''), ' '," +
						"coalesce(asgCliente.asgClienteApellidoCasada, ''))) like upper(?) or" +
				"	upper(coalesce(asgCliente.asgClienteNombreComercial, '')) like upper(?)" +
				")";
			parameters.add("%" + StringUtils.replace(asgSeguroForm.getAsgClienteNombreCompleto(), " ", "%") + "%");
			parameters.add("%" + StringUtils.replace(asgSeguroForm.getAsgClienteNombreCompleto(), " ", "%") + "%");
			addAnd = true;
		}
		if(StringUtils.isNotBlank(asgSeguroForm.getAsgPolizaNumero())){
			where += (addAnd ? " and " : "") + " asgPoliza.asgPolizaNumero like upper(?) ";
			parameters.add("%" + asgSeguroForm.getAsgPolizaNumero() + "%");
			addAnd = true;
		}
		if("reclamo".equalsIgnoreCase(type)){
			if("0".equals(asgSeguroForm.getAsgFinalizado())){
				where += (addAnd ? " and " : "") + 
					" (" +
					"	select count(*) " +
					"	from AsgReclamo asgReclamo " +
					"	where asgReclamo.asgPoliza.asgPolizaId = asgPoliza.asgPolizaId and " +
					"	(asgReclamo.asgReclamoFinalizado is null or asgReclamo.asgReclamoFinalizado = '0')" +
					" ) > 0 ";
			}else if("1".equals(asgSeguroForm.getAsgFinalizado())){
				where += (addAnd ? " and " : "") + 
					" (" +
					"	select count(*) " +
					"	from AsgReclamo asgReclamo" +
					"	where asgReclamo.asgPoliza.asgPolizaId = asgPoliza.asgPolizaId and " +
					"		 asgReclamo.asgReclamoFinalizado = '1'" +
					" ) > 0 ";
			}
		}else if("pendiente".equalsIgnoreCase(type)){
			if("0".equals(asgSeguroForm.getAsgFinalizado())){
				where += (addAnd ? " and " : "") + 
					" (" +
					"	select count(*) " +
					"	from AsgPendiente asgPendiente" +
					"	where asgPendiente.asgPoliza.asgPolizaId = asgPoliza.asgPolizaId and " +
					"		(asgPendiente.asgPendienteFinalizado is null or asgPendiente.asgPendienteFinalizado = '0')" +
					"	) > 0 ";
			}else if("1".equals(asgSeguroForm.getAsgFinalizado())){
				where += (addAnd ? " and " : "") + 
					" (" +
					"	select count(*) " +
					"	from AsgPendiente asgPendiente" +
					"	where asgPendiente.asgPoliza.asgPolizaId = asgPoliza.asgPolizaId and " +
					"		asgPendiente.asgPendienteFinalizado = '1') > 0 ";
			}
		}
		hqlQuery = StringUtils.replace(hqlQuery, "{WHERE}", StringUtils.isNotBlank(where) ? (" where " + where) : "");
		try {
			return (List<Object[]>) findByHQLQuery(hqlQuery, parameters.toArray());
		} catch (Exception e) {
			throw new WebException("Problemas al ejecutar la busqueda de clientes y polizas");
		}		
	}
	
	@SuppressWarnings("unchecked")
	public List<AsgPoliza> findAllByParameters(AsgSeguroForm asgSeguroForm){
		try {
			DetachedCriteria criteria = DetachedCriteria.forClass(AsgPoliza.class);
			criteria.addOrder(Order.asc("asgCliente.asgClienteId"));
			criteria.addOrder(Order.asc("asgPolizaNumero"));
			criteria.addOrder(Order.asc("asgPolizaFechaCreacion"));
			criteria.createAlias("ctgTipoSeguro", "ctgTipoSeguro", Criteria.LEFT_JOIN);
			criteria.createAlias("ctgPlan", "ctgPlan", Criteria.LEFT_JOIN);
			criteria.createAlias("ctgAsesor", "ctgAsesor", Criteria.LEFT_JOIN);
			criteria.createAlias("ctgFormaPago", "ctgFormaPago", Criteria.LEFT_JOIN);
			criteria.createAlias("ctgAseguradora", "ctgAseguradora", Criteria.LEFT_JOIN);
			return (List<AsgPoliza>) findByCriteria(criteria);
		} catch (Exception e) {
			logger.error("Exception:", e);
			e.printStackTrace();
		}
		return Collections.emptyList();
	}
}